index.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import { useParams } from 'common'
  2. import { useRouter } from 'next/router'
  3. import { useEffect, useMemo } from 'react'
  4. import { Admonition } from 'ui-patterns'
  5. import { PageContainer } from 'ui-patterns/PageContainer'
  6. import {
  7. PageHeader,
  8. PageHeaderDescription,
  9. PageHeaderMeta,
  10. PageHeaderSummary,
  11. PageHeaderTitle,
  12. } from 'ui-patterns/PageHeader'
  13. import { PageSection, PageSectionContent } from 'ui-patterns/PageSection'
  14. import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
  15. import { useAvailableIntegrations } from '@/components/interfaces/Integrations/Landing/useAvailableIntegrations'
  16. import { useInstalledIntegrations } from '@/components/interfaces/Integrations/Landing/useInstalledIntegrations'
  17. import { DefaultLayout } from '@/components/layouts/DefaultLayout'
  18. import { ProjectIntegrationsLayoutDispatch } from '@/components/layouts/ProjectIntegrationsLayoutDispatch'
  19. import type { NextPageWithLayout } from '@/types'
  20. const IntegrationPage: NextPageWithLayout = () => {
  21. const router = useRouter()
  22. const { ref, id, pageId, childId } = useParams()
  23. const { data: allIntegrations } = useAvailableIntegrations()
  24. const { installedIntegrations: installedIntegrations, isLoading: isIntegrationsLoading } =
  25. useInstalledIntegrations()
  26. // everything is wrapped in useMemo to avoid UI resets when installing additional extensions like pg_net
  27. const integration = useMemo(() => allIntegrations.find((i) => i.id === id), [allIntegrations, id])
  28. const installation = useMemo(
  29. () => installedIntegrations.find((inst) => inst.id === id),
  30. [installedIntegrations, id]
  31. )
  32. // Get the corresponding component dynamically
  33. const Component = useMemo(
  34. () => integration?.navigate({ id, pageId, childId }),
  35. [integration, id, pageId, childId]
  36. )
  37. useEffect(() => {
  38. // if the integration is not installed, redirect to the overview page
  39. if (
  40. router &&
  41. router?.isReady &&
  42. !isIntegrationsLoading &&
  43. !installation &&
  44. pageId !== 'overview'
  45. ) {
  46. router.replace(`/project/${ref}/integrations/${id}/overview`)
  47. }
  48. }, [installation, isIntegrationsLoading, pageId, router, ref, id])
  49. // Determine content based on state
  50. const content = useMemo(() => {
  51. if (!router?.isReady || isIntegrationsLoading) {
  52. return (
  53. <PageContainer size="full">
  54. <PageSection>
  55. <PageSectionContent>
  56. <GenericSkeletonLoader />
  57. </PageSectionContent>
  58. </PageSection>
  59. </PageContainer>
  60. )
  61. } else if (!Component || !id || !integration) {
  62. return (
  63. <PageContainer size="full">
  64. <PageHeader size="full">
  65. <PageHeaderMeta>
  66. <PageHeaderSummary>
  67. <PageHeaderTitle>Integration not found</PageHeaderTitle>
  68. <PageHeaderDescription>
  69. If you think this is an error, please contact support.
  70. </PageHeaderDescription>
  71. </PageHeaderSummary>
  72. </PageHeaderMeta>
  73. </PageHeader>
  74. <PageSection>
  75. <PageSectionContent>
  76. <Admonition type="warning" title="This integration is not currently available">
  77. Please try again later or contact support if the problem persists.
  78. </Admonition>
  79. </PageSectionContent>
  80. </PageSection>
  81. </PageContainer>
  82. )
  83. } else {
  84. return <Component />
  85. }
  86. }, [router?.isReady, isIntegrationsLoading, id, integration, Component])
  87. return content
  88. }
  89. IntegrationPage.getLayout = (page) => (
  90. <DefaultLayout>
  91. <ProjectIntegrationsLayoutDispatch>{page}</ProjectIntegrationsLayoutDispatch>
  92. </DefaultLayout>
  93. )
  94. export default IntegrationPage